/*
 * Robust Pointers - A framework for robust pointers in a MT environment.
 * http://code.google.com/p/rptr/
 *
 * Copyright (c) 2009, Bill K. Barekas <bbarekas@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *    3. Neither the name of the author nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file    test_rptr_01.c
 * @author  Bill K. Barekas <bbarekas@gmail.com>
 * @date    October 24, 2009
 * @version $Id$
 *
 * This file contains the error string definitions.
 */



#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>

#include "rptr.h"
#include "rptr_error.h"


/**
 * Global variables
 */
rptr_type MY_TYPE1_ID;

/**
 * RPTR configuration.
 */
rptr_conf  configuration =
{
  0,                // flags;
  16,               // min_objs;
  1024,             // max_objs;
  16,               // inc_step;
  60                // reuse_period;

};



/**
 * simple_type1 structure.
 */
struct simple_type1_s {
  uint32_t                   id;
  uint32_t                   size;
  char *                     buff;
};
typedef struct simple_type1_s          simple_type1;


/**
 * register_types
 *
 */
int
register_types()
{

  /* Register simple_type1. */
  MY_TYPE1_ID = rptr_new_type("My type 1", "TYP1", sizeof(simple_type1));
  printf("MY_TYPE1_ID:%d registered ...\n", MY_TYPE1_ID);

  return 0;
}


/**
 * simple_type1_init
 */
rptr
simple_type1_create()
{
  simple_type1 *   type1;
  rptr             rptr;

  /* Allocate memory for the obj. */
  type1 = malloc(sizeof(*type1));
  if (type1 == NULL) {
    return NULL;
  }

  /* Initialize the structure. */
  type1->id = 1234;
  type1->size = 4321;
  type1->buff = malloc(type1->size);

  /* Register object to RPTR. */
  rptr = rptr_add(MY_TYPE1_ID, type1, type1->id);
  if (rptr == NULL) {
    printf("ERROR: rptr_add failed for MY_TYPE1_ID. %s.\n", rptr_error_str(rptr_errno));
  }

  return rptr;
}


/**
 * simple_type1_destroy
 */
int
simple_type1_destroy(void * prt, int error)
{
  simple_type1 *   type1;

  type1 = (simple_type1 *)prt;


  if (type1->buff) {
    free(type1->buff);
  }

  //printf("type1 destroy.\n");

  return 0;
}

/**
 * test_error
 *
 */
int
test_error()
{
  int i;

  rptr_stats(" STEP 0 - test_error ... ");

  fprintf(stderr, "RPTR: Error code:%d - %s\n", 1, rptr_error_str(1));
  fprintf(stderr, "RPTR: Error code:%d - %s\n", 0, rptr_error_str(0));
  fprintf(stderr, "RPTR: Error code:%d - %s\n", -1, rptr_error_str(-1));

  for (i = 0; i <= RPTR_ERROR_MAX; i++) {
    fprintf(stderr, "RPTR: Error code:%d - %s\n", -i, rptr_error_str(-i));
  }
}

/**
 * Main
 */
int
main(void)
{
  int ret;
  uint64_t id;
  simple_type1 * objs1[100];
  int i;


  printf("START: rptr test ... \n");

  /* Initialize RPTR library. */
  ret = rptr_init(&configuration);
  if (ret) {
    fprintf(stderr, "ERROR: rptr_init failed.\n");
    return 1;
  }

  /* Test error handling. */
  test_error();

  sleep(1);
  rptr_stats(" STEP 1 - Register types ... ");
  sleep(1);

  /* Register all types. */
  ret = register_types();

  sleep(1);
  rptr_stats(" STEP 2 - Create objects ... ");
  sleep(1);

  for (i = 0; i < 16; i++) {
    objs1[i] = simple_type1_create(MY_TYPE1_ID);
    id = rptr_get_id(objs1[i]);
    if (id == 0) {
      printf("CREAT: ap[%d]:%p --> %s\n", i, objs1[i], rptr_error_str(rptr_errno));
    }
    else {
      printf("CREAT: ap[%d]:%p --> OID:0x%016llx\n", i, objs1[i], id);
    }
  }

  sleep(1);
  rptr_stats(" STEP 3 - Create MORE objects ... ");
  sleep(1);

  for (i = 16; i < 33; i++) {
    objs1[i] = simple_type1_create(MY_TYPE1_ID);
    id = rptr_get_id(objs1[i]);
    if (id == 0) {
      printf("CREAT: ap[%d]:%p --> %s\n", i, objs1[i], rptr_error_str(rptr_errno));
    }
    else {
      printf("CREAT: ap[%d]:%p --> OID:0x%016llx\n", i, objs1[i], id);
    }
  }

  sleep(1);
  rptr_stats(" STEP 4 - Finish ... ");
  sleep(1);

  printf("exiting ...\n");

  return EXIT_SUCCESS;

}
